"""
闭包：
    1、什么是闭包：定义双层嵌套函数，内层函数可以访问外层函数的变量，将内层函数作为外部函数的返回值返回，，此内层函数就是闭包函数
    2、闭包的优点：
        1）不定义全局变量，也可以试函数持续访问和修改一个变量
        2）闭包函数引用的外部变量，是外层函数的内部变量，作用域封闭难以被误修改
    3、闭包的缺点：
        1）会额外占用内存
    4、闭包函数如何修改外部函数的变量：
        在闭包函数中使用 nonlocal声明外部变量，即可进行修改

装饰器：
    1、装饰器：创建闭包函数，在闭包函数内调用目标函数，达到不改动目标函数的同时，增加额外的功能
    2、写法：
        # 闭包函数
        def outer(func):
            def inter():
                print("xxx")
                func()
                print("yyy")
            return inter
       -----------------
        # 装饰器语法糖写法
        @outer         # 将下面的目标函数作为func参数传入闭包函数中
        # 目标函数
        def sleep():
            print("****")

        # 调用目标函数
        sleep()
        -----------------
        # 不适用装饰器的写法
        def sleep():
            print("//////")

        ot = outer(sleep)
        ot()
        ------------------

单例模式：

工厂模式：
"""
def out_func(out_var):

    def int_func():
        nonlocal out_var   # 声明外部函数的变量 供内部函数修改 不修改的话可以不用写
        print(out_var*10)
    return int_func    # 内部函数作为返回值

ot1 = out_func(10)
ot1()
ot2 = out_func(20)
ot2()
# --------------


# 闭包函数
def outer(func):
    def inter():
        print("xxx")
        func()
        print("yyy")
    return inter

# ----------装饰器
@outer    # 装饰器语法糖写法，将下面的目标函数作为参数传入outer函数中
def sleep():
    print("装饰器******")

sleep()

# 不使用装饰器的写法
def sleep():
    print("非装饰器******")

ot = outer(sleep)
ot()

def out_fun(num):         # 外部函数
    def int_fun(x):       # 内部函数
        x += num          # 内部函数可以引用外部函数的变量 num
        print(f"输出num：{x}")
    return int_fun

out1 = out_fun(5)     # 外部函数的传参 5 返回值是一个函数体
out1(10)              # 内部函数的传参 10  调用函数体





def tager_fun(func):     # 目标函数
    def wrapper():
        print("这里是调用前")
        func()          # 调用功能函数
        print("这里是调用后")
    return wrapper  # 返回闭包函数

@tager_fun      # 装饰器 相当于 func = tager_fun(func)
def func():     # 被装饰的函数
    print("我加入进来了！")

func()  # 调用被装饰的函数 相当于 func() = tager_fun(func)






